package com.example.exercise.jasper;

import jakarta.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRGraphics2DExporter;
import net.sf.jasperreports.engine.export.JRGraphics2DExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.ooxml.JRDocxExporter;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.engine.fill.JRAbstractLRUVirtualizer;
import net.sf.jasperreports.engine.fill.JRGzipVirtualizer;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.export.ExporterInput;
import net.sf.jasperreports.export.OutputStreamExporterOutput;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import org.springframework.core.io.ClassPathResource;

import javax.imageio.ImageIO;
import javax.sql.DataSource;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class JasperUtils {

    public static void showPdfByJdbc(HttpServletResponse response, DataSource dataSource, String filePath, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        Connection connection = null;
        OutputStream outputStream = null;
        try {
            in = resource.getInputStream();
            connection = dataSource.getConnection();
            outputStream = response.getOutputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);
            JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
        } catch (JRException | SQLException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStream, connection);
        }
    }

    public static <T> void showPdfByJavaBean(HttpServletResponse response, List<T> list, String filePath, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStream outputStream = null;
        try {
            in = resource.getInputStream();
            outputStream = response.getOutputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            JasperPrint jasperPrint;
            if (list == null || list.isEmpty()) {
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
            } else {
                JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(list);
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
            }
            JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
        } catch (JRException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStream, null);
        }
    }

    public static void showImgByJdbc(HttpServletResponse response, DataSource dataSource, String filePath, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        Connection connection = null;
        OutputStream outputStream = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            connection = dataSource.getConnection();
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);
            outputStream = response.getOutputStream();
            JRGraphics2DExporter exporter = new JRGraphics2DExporter();
            BufferedImage bufferedImage = new BufferedImage(jasperPrint.getPageWidth() * 4, jasperPrint.getPageHeight() * 4, BufferedImage.TYPE_INT_BGR);
            Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
            exporter.setParameter(JRGraphics2DExporterParameter.GRAPHICS_2D, g);
            exporter.setParameter(JRGraphics2DExporterParameter.ZOOM_RATIO, 4.0f);
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.exportReport();
            g.dispose();
            ImageIO.write(bufferedImage, "JPEG", outputStream);
        } catch (JRException | SQLException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStream, connection);
        }
    }

    public static <T> void showImgByJavaBean(HttpServletResponse response, List<T> list, String filePath, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStream outputStream = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            JasperPrint jasperPrint;
            if (list == null || list.isEmpty()) {
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
            } else {
                JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(list);
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
            }
            outputStream = response.getOutputStream();
            JRGraphics2DExporter exporter = new JRGraphics2DExporter();
            BufferedImage bufferedImage = new BufferedImage(jasperPrint.getPageWidth() * 4, jasperPrint.getPageHeight() * 4, BufferedImage.TYPE_INT_BGR);
            Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
            exporter.setParameter(JRGraphics2DExporterParameter.GRAPHICS_2D, g);
            exporter.setParameter(JRGraphics2DExporterParameter.ZOOM_RATIO, 4.0f);
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.exportReport();
            g.dispose();
            ImageIO.write(bufferedImage, "JPEG", outputStream);
        } catch (JRException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStream, null);
        }
    }

    private static void close(InputStream in, OutputStream outputStream, Connection connection) {
        try {
            if (in != null) {
                in.close();
            }
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (IOException | SQLException e) {
            e.printStackTrace();
        }
    }

    private static void close(InputStream in, OutputStreamExporterOutput outputStreamExporterOutput, Connection connection) {
        try {
            if (in != null) {
                in.close();
            }
            if (outputStreamExporterOutput != null) {
                outputStreamExporterOutput.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (IOException | SQLException e) {
            e.printStackTrace();
        }
    }

    public static void outputPdfByJdbc(HttpServletResponse response, DataSource dataSource, String filePath, String fileName, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStreamExporterOutput outputStreamExporterOutput = null;
        Connection connection = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            connection = dataSource.getConnection();
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);
            JRPdfExporter exporter = new JRPdfExporter();
            ExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
            exporter.setExporterInput(exporterInput);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("utf-8");
            fileName = new String(fileName.getBytes("gb2312"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            outputStreamExporterOutput = new SimpleOutputStreamExporterOutput(response.getOutputStream());
            exporter.setExporterOutput(outputStreamExporterOutput);
            exporter.exportReport();
        } catch (JRException | SQLException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStreamExporterOutput, connection);
        }
    }


    public static <T> void outputPdfByJavaBean(HttpServletResponse response, List<T> list, String filePath, String fileName, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStreamExporterOutput outputStreamExporterOutput = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            JasperPrint jasperPrint = null;
            if (list == null || list.isEmpty()) {
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
            } else {
                JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(list);
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
            }
            JRPdfExporter exporter = new JRPdfExporter();
            ExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
            exporter.setExporterInput(exporterInput);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("utf-8");
            fileName = new String(fileName.getBytes("gb2312"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            outputStreamExporterOutput = new SimpleOutputStreamExporterOutput(response.getOutputStream());
            exporter.setExporterOutput(outputStreamExporterOutput);
            exporter.exportReport();
        } catch (JRException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStreamExporterOutput, null);
        }
    }

    public static void outputXlsxByJdbc(HttpServletResponse response, DataSource dataSource, String filePath, String fileName, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStreamExporterOutput outputStreamExporterOutput = null;
        Connection connection = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            connection = dataSource.getConnection();
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);
            JRXlsxExporter exporter = new JRXlsxExporter();
            ExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
            exporter.setExporterInput(exporterInput);
            fileName = new String(fileName.getBytes("gb2312"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("utf-8");
            outputStreamExporterOutput = new SimpleOutputStreamExporterOutput(response.getOutputStream());
            exporter.setExporterOutput(outputStreamExporterOutput);
            exporter.exportReport();
        } catch (JRException | SQLException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStreamExporterOutput, connection);
        }
    }

    public static <T> void outputXlsxByJavaBean(HttpServletResponse response, List<T> list, String filePath, String fileName, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStreamExporterOutput outputStreamExporterOutput = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            JasperPrint jasperPrint = null;
            if (list == null || list.isEmpty()) {
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
            } else {
                JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(list);
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
            }
            JRXlsxExporter exporter = new JRXlsxExporter();
            ExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
            exporter.setExporterInput(exporterInput);
            fileName = new String(fileName.getBytes("gb2312"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("utf-8");
            outputStreamExporterOutput = new SimpleOutputStreamExporterOutput(response.getOutputStream());
            exporter.setExporterOutput(outputStreamExporterOutput);
            exporter.exportReport();
        } catch (JRException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStreamExporterOutput, null);
        }
    }

    public static void outputDocxByJdbc(HttpServletResponse response, DataSource dataSource, String filePath, String fileName, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStreamExporterOutput outputStreamExporterOutput = null;
        Connection connection = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            connection = dataSource.getConnection();
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);
            JRDocxExporter exporter = new JRDocxExporter();
            ExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
            exporter.setExporterInput(exporterInput);
            fileName = new String(fileName.getBytes("gb2312"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("utf-8");
            outputStreamExporterOutput = new SimpleOutputStreamExporterOutput(response.getOutputStream());
            exporter.setExporterOutput(outputStreamExporterOutput);
            exporter.exportReport();
        } catch (JRException | SQLException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStreamExporterOutput, connection);
        }
    }

    public static <T> void outputDocxByJavaBean(HttpServletResponse response, List<T> list, String filePath, String fileName, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        OutputStreamExporterOutput outputStreamExporterOutput = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            JasperPrint jasperPrint = null;
            if (list == null || list.isEmpty()) {
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
            } else {
                JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(list);
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
            }
            JRDocxExporter exporter = new JRDocxExporter();
            ExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
            exporter.setExporterInput(exporterInput);
            fileName = new String(fileName.getBytes("gb2312"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("utf-8");
            outputStreamExporterOutput = new SimpleOutputStreamExporterOutput(response.getOutputStream());
            exporter.setExporterOutput(outputStreamExporterOutput);
            exporter.exportReport();
        } catch (JRException | IOException e) {
            e.printStackTrace();
        } finally {
            close(in, outputStreamExporterOutput, null);
        }
    }

    public static <T> void printReportByJaveBean(List<T> list, String filePath, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            JasperPrint jasperPrint = null;
            if (list == null || list.isEmpty()) {
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
            } else {
                JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(list);
                jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
            }
            JasperPrintManager.printReport(jasperPrint, true);
        } catch (JRException | IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void printReportByJdbc(DataSource dataSource, String filePath, Map<String, Object> parameters) {
        JRAbstractLRUVirtualizer virtualizer = new JRGzipVirtualizer(3);
        parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
        ClassPathResource resource = new ClassPathResource(filePath);
        InputStream in = null;
        Connection connection = null;
        try {
            in = resource.getInputStream();
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(in);
            connection = dataSource.getConnection();
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);
            JasperPrintManager.printReport(jasperPrint, true);
        } catch (JRException | IOException | SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (IOException | SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
